import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
import numpy as np

from stock_data import StockDataManager
import config

# 页面配置
st.set_page_config(
    page_title=config.APP_TITLE,
    page_icon="📊",
    layout="wide"
)

# 初始化股票数据管理器
@st.cache_resource
def get_stock_manager():
    return StockDataManager()

def main():
    # 页面标题
    st.title(config.APP_TITLE)
    st.markdown(config.APP_DESCRIPTION)
    
    # 侧边栏配置
    st.sidebar.header("参数设置")
    
    top_volume = st.sidebar.slider(
        "昨日成交量前N名", 
        min_value=10, 
        max_value=300, 
        value=config.DEFAULT_TOP_VOLUME,
        step=10
    )
    
    top_drop = st.sidebar.slider(
        "今日跌幅前M名", 
        min_value=5, 
        max_value=50, 
        value=config.DEFAULT_TOP_DROP,
        step=5
    )
    
    # 获取数据按钮
    if st.sidebar.button("分析股票"):
        with st.spinner("正在获取和分析股票数据..."):
            try:
                stock_manager = get_stock_manager()
                data, error = stock_manager.get_top_price_drop_stocks(top_volume, top_drop)
                
                if error:
                    st.error(f"获取数据失败: {error}")
                elif data.empty:
                    st.warning("没有找到符合条件的股票数据")
                else:
                    # 显示结果
                    st.subheader(f"昨日成交量前{top_volume}名中今日开盘价跌幅最大的{top_drop}只股票")
                    
                    # 确保数据中有必要的列
                    required_columns = ['ts_code', 'name', 'open', 'close', 'high', 'low', 'vol', 'amount', 'drop_percent']
                    for col in required_columns:
                        if col not in data.columns:
                            if col == 'amount' and 'amount' not in data.columns:
                                # 如果没有成交额列，用成交量*价格估算
                                data['amount'] = data['vol'] * data['close']
                            elif col == 'name' and 'name' not in data.columns:
                                # 如果没有名称列，使用代码作为名称
                                data['name'] = data['ts_code']
                            else:
                                # 其他缺失列填充为0
                                data[col] = 0
                    
                    # 显示数据表格
                    display_columns = ['ts_code', 'name', 'open', 'close', 'drop_percent']
                    display_data = data[display_columns].copy()
                    # 格式化数值
                    display_data['drop_percent'] = display_data['drop_percent'].map(lambda x: f"{x:.2f}%")
                    display_data['open'] = display_data['open'].map(lambda x: f"{x:.2f}")
                    display_data['close'] = display_data['close'].map(lambda x: f"{x:.2f}")
                    
                    st.dataframe(display_data, use_container_width=True)
                    
                    # 创建可视化图表
                    create_visualizations(data)
                    
                    # 显示详细信息
                    show_detailed_info(data)
            except Exception as e:
                st.error(f"分析过程中出错: {str(e)}")
    else:
        # 首次加载页面时显示的内容
        st.info("👈 请在左侧设置参数并点击'分析股票'按钮开始分析")
        st.markdown("""
        ### 使用说明
        
        本应用分析A股市场数据，找出昨日成交量前N名股票中今日开盘价跌幅最大的M只股票。
        
        #### 功能特点
        
        - **数据来源**：使用AKShare API获取A股市场实时数据
        - **分析维度**：结合成交量和价格跌幅进行多维度分析
        - **可视化展示**：直观展示分析结果
        - **详细信息**：提供每只股票的详细信息
        
        #### 使用方法
        
        1. 在左侧边栏设置参数
        2. 点击"分析股票"按钮
        3. 查看分析结果和可视化图表
        """)

def create_visualizations(data):
    """创建数据可视化图表"""
    st.subheader("数据可视化")
    
    try:
        # 创建两列布局
        col1, col2 = st.columns(2)
        
        with col1:
            # 跌幅排名条形图
            try:
                # 确保数据不为空
                if len(data) > 0:
                    fig_drop = px.bar(
                        data.sort_values('drop_percent', ascending=True).head(10),
                        y='ts_code',
                        x='drop_percent',
                        orientation='h',
                        title="跌幅排名",
                        labels={'drop_percent': '跌幅(%)', 'ts_code': '股票代码'},
                        color='drop_percent',
                        color_continuous_scale='Reds'
                    )
                    fig_drop.update_layout(height=500)
                    st.plotly_chart(fig_drop, use_container_width=True)
                else:
                    st.info("没有足够的数据来创建跌幅排名图表")
            except Exception as e:
                st.warning(f"创建跌幅排名图表时出错: {str(e)}")
        
        with col2:
            # 行业分布饼图
            try:
                # 确保industry列存在且有值
                if 'industry' in data.columns and not data['industry'].isna().all():
                    industry_counts = data['industry'].value_counts().reset_index()
                    industry_counts.columns = ['industry', 'count']
                    
                    fig_industry = px.pie(
                        industry_counts,
                        values='count',
                        names='industry',
                        title="行业分布",
                        hole=0.4
                    )
                    fig_industry.update_layout(height=500)
                    st.plotly_chart(fig_industry, use_container_width=True)
                else:
                    st.info("缺少行业数据，无法创建行业分布图表")
            except Exception as e:
                st.warning(f"创建行业分布图表时出错: {str(e)}")
        
        # 成交量与跌幅散点图
        try:
            # 确保必要的列都存在
            required_cols = ['vol', 'drop_percent', 'amount', 'industry', 'ts_code']
            if all(col in data.columns for col in required_cols) and len(data) > 0:
                # 处理可能的NaN值
                scatter_data = data.copy()
                for col in ['vol', 'drop_percent', 'amount']:
                    scatter_data[col] = scatter_data[col].fillna(0)
                
                # 如果industry列有NaN值，填充为'未知'
                if 'industry' in scatter_data.columns:
                    scatter_data['industry'] = scatter_data['industry'].fillna('未知')
                
                fig_scatter = px.scatter(
                    scatter_data,
                    x='vol',
                    y='drop_percent',
                    size='amount',
                    color='industry',
                    hover_name='ts_code',
                    title="成交量与跌幅关系",
                    labels={'vol': '成交量', 'drop_percent': '跌幅(%)', 'amount': '成交额', 'industry': '行业'}
                )
                fig_scatter.update_layout(height=600)
                st.plotly_chart(fig_scatter, use_container_width=True)
            else:
                st.info("缺少必要的数据列，无法创建散点图")
        except Exception as e:
            st.warning(f"创建散点图时出错: {str(e)}")
    except Exception as e:
        st.error(f"创建可视化图表时出错: {str(e)}")

def show_detailed_info(data):
    """显示股票的详细信息"""
    st.subheader("股票详细信息")
    
    try:
        # 确保必要的列存在
        required_columns = ['ts_code', 'name', 'open', 'close', 'high', 'low', 'vol', 'amount', 'drop_percent', 'industry']
        for col in required_columns:
            if col not in data.columns:
                if col == 'industry':
                    data['industry'] = '未知'
                elif col in ['high', 'low'] and 'open' in data.columns and 'close' in data.columns:
                    # 如果没有最高/最低价，用开盘/收盘价代替
                    data['high'] = data[['open', 'close']].max(axis=1)
                    data['low'] = data[['open', 'close']].min(axis=1)
                elif col == 'amount' and 'vol' in data.columns and 'close' in data.columns:
                    # 如果没有成交额，用成交量*收盘价估算
                    data['amount'] = data['vol'] * data['close']
                else:
                    # 其他缺失列填充为0
                    data[col] = 0
        
        # 创建选择框让用户选择股票
        stock_options = [f"{row['ts_code']} - {row['name']}" for _, row in data.iterrows()]
        
        if stock_options:
            selected_stock = st.selectbox("选择股票查看详细信息", stock_options)
            
            if selected_stock:
                # 提取股票代码
                ts_code = selected_stock.split(" - ")[0]
                
                # 获取选中股票的数据
                stock_data = data[data['ts_code'] == ts_code].iloc[0]
                
                # 创建三列布局
                col1, col2, col3 = st.columns(3)
                
                with col1:
                    st.metric("股票名称", stock_data['name'])
                    st.metric("所属行业", stock_data['industry'])
                    st.metric("跌幅(%)", f"{stock_data['drop_percent']:.2f}%")
                
                with col2:
                    st.metric("开盘价", f"{stock_data['open']:.2f}")
                    st.metric("收盘价", f"{stock_data['close']:.2f}")
                    st.metric("最高价", f"{stock_data['high']:.2f}")
                
                with col3:
                    st.metric("最低价", f"{stock_data['low']:.2f}")
                    st.metric("成交量", f"{stock_data['vol']/10000:.2f}万手")
                    st.metric("成交额", f"{stock_data['amount']/10000:.2f}万元")
                
                # 添加K线图的占位符（实际项目中可以添加历史K线图）
                st.info("在实际项目中，这里可以添加该股票的历史K线图和更多技术指标")
        else:
            st.info("没有可用的股票数据")
    except Exception as e:
        st.error(f"显示详细信息时出错: {str(e)}")

if __name__ == "__main__":
    main()
